package com.penghaisoft.microwms.materialhand.web.outwarehouse.service.impl;

import com.penghaisoft.microwms.common.Constant;
import com.penghaisoft.microwms.common.data.model.RawRequisitionSn;
import com.penghaisoft.microwms.common.dto.HandResp;
import com.penghaisoft.microwms.common.dto.RawOrderOutDto;
import com.penghaisoft.microwms.common.dto.RawOrderOutSnDto;
import com.penghaisoft.microwms.common.service.BaseService;
import com.penghaisoft.microwms.common.wms.model.RawStorageSn;
import com.penghaisoft.microwms.materialhand.web.outwarehouse.dao.RawOrderOutMapper;
import com.penghaisoft.microwms.materialhand.web.outwarehouse.dao.RawOrderOutSnMapper;
import com.penghaisoft.microwms.materialhand.web.outwarehouse.dao.RawRequisitionSnMapper;
import com.penghaisoft.microwms.materialhand.web.outwarehouse.service.RawOrderOutSnService;
import com.penghaisoft.microwms.materialhand.web.storage.dao.RawStorageSnMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * Created by 王治国 on 2018/5/31.
 */
@Service
public class RawOrderOutSnServiceImpl extends BaseService implements RawOrderOutSnService {

    @Autowired
    private RawOrderOutSnMapper rawOrderOutSnMapper;

    @Autowired
    private RawOrderOutMapper rawOrderOutMapper;

    @Autowired
    private RawStorageSnMapper rawStorageSnMapper;

    @Autowired
    private RawRequisitionSnMapper rawRequisitionSnMapper;

    /**
     * 根据条码号查询
     *
     * @param rawOrderOutSnDto
     * @return
     * @wzhg 1866
     */
    @Override
    public List<RawRequisitionSn> findByCode(@Param("entity") RawOrderOutSnDto rawOrderOutSnDto) {
        return rawOrderOutSnMapper.findByCode(rawOrderOutSnDto);
    }

    @Override
    public Integer createCode(@Param("entity") RawRequisitionSn requisitionSn) {
        return rawOrderOutSnMapper.createCode(requisitionSn);
    }

    @Override
    public List<RawOrderOutSnDto> findInfoByPE(@Param("entity") RawOrderOutDto rawOrderOutDto) {
        return rawOrderOutSnMapper.findInfoByPE(rawOrderOutDto);
    }

    @Override
    public List<RawOrderOutSnDto> findInfoByPE1(@Param("entity") RawOrderOutDto rawOrderOutDto) {
        return rawOrderOutSnMapper.findInfoByPE1(rawOrderOutDto);
    }

    @Override
    public List<RawOrderOutSnDto> findInfoByPE2(@Param("entity") RawOrderOutDto rawOrderOutDto) {
        return rawOrderOutSnMapper.findInfoByPE2(rawOrderOutDto);
    }
    /**
     * @param rawOrderOutSnDto
     * @return
     * @wzhg 18612 根据PE管的扫码进度修改出库明细表中对应长度的钢管的配套状态 0：未开始 1：配套中 2：完成
     */
    @Override
    public Integer updateUdf1(RawOrderOutSnDto rawOrderOutSnDto) {
        return rawOrderOutSnMapper.updateUdf1(rawOrderOutSnDto);
    }

    /**
     * @param storageSn
     * @param rawOrderOutSnDto
     * @return
     * @wzhg 1866 PE管扫描 精准匹配
     */
    @Override
    @Transactional
    public HandResp scanPE(RawOrderOutSnDto rawOrderOutSnDto, RawStorageSn storageSn) {
        HandResp resp = new HandResp();
        Boolean a = false;  // 判断PE管长度与已扫的各个钢管的长度是否匹配
        int upt = 0;
        Long countLW = 0l; // 正在扫描的PE管对应的钢管型号的已扫总数（所有长度）
        Long countPE = 0l; // 正在扫描的PE管归属型号的已扫总数（所有长度的都包含）
        Long ctLW = 0l; //    正在扫描的PE管对应长度的钢管的已扫数量
        Long ctPE = 0l; //    正在扫描的PE管对应的型号，长度的已扫数量，最终 ctPE 与 ctLW相等，该长度的PE管就算扫完了
        int flag = 0;
        // 3.判断型号数量是否等于需求，达到需求值，不允许再扫，如果没达到，继续
        // 3.根据条码归属的【领料单号、合同号和型号】查询主表信息,判断订单下该型号扫描数量是否已经达到需求数量
        RawOrderOutDto orderOutDtoPE = new RawOrderOutDto(); // PE管
        RawOrderOutDto orderOutDtoLW = new RawOrderOutDto(); // 钢管
        orderOutDtoPE.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());
        orderOutDtoPE.setContractNo(storageSn.getContractNo());
        orderOutDtoPE.setModel(storageSn.getModel());

        // 该步骤只是为了卡住 事物，没有对数据库进行实际有影响的操作 修改领料单 active_flag 为 1 （原值就是 1）
        rawOrderOutMapper.updateOrderStatus(orderOutDtoPE);
        List<RawOrderOutDto> orderOutDtosPE = rawOrderOutMapper.findOrderInfo(orderOutDtoPE);
        if (orderOutDtosPE.size() == 0) {
            resp.setCode(Constant.FAIL);
            resp.setMsg("该领料单内不包含该条码型号！");
            return resp;
        } else {
            orderOutDtoPE = orderOutDtosPE.get(0);
            // 用id区别PE管和钢管 后续操作以requisitionId作为身份牌
            // 根据PE管的领料单查到对应的钢管领料信息,判断钢管是否全部扫完，钢管没扫完，不允许扫PE管
            orderOutDtoLW.setContractNo(storageSn.getContractNo());
            orderOutDtoLW.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());
            List<RawOrderOutDto> orderOutDtosLW = rawOrderOutMapper.findOrderInfo(orderOutDtoLW);

            for (RawOrderOutDto order : orderOutDtosLW) {
                if (Constant.MODEL_W.equals(order.getModelType()) || Constant.MODEL_L.equals(order.getModelType())) {
                    orderOutDtoLW = order; // PE管对应的钢管领料信息
                    flag = 1;
                }
            }
            if (flag == 0) {
                resp.setCode(Constant.FAIL);
                resp.setMsg("找不到与该PE管对应的钢管领料信息，请核查！");
                return resp;
            }
            // 取消 必须先扫完钢管才能扫PE管的 限制，可以扫一根钢管就扫一根PE管
/*            if ("0".equals(orderOutDtoLW.getRequisitionStatus()) || "1".equals(orderOutDtoLW.getRequisitionStatus())){
                resp.setCode(Constant.FAIL);
                resp.setMsg("该PE管对应的钢管扫码尚未完成，请先扫钢管！");
                return resp;
            }*/
            // 查询对应的钢管明细，根据长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
            List<RawOrderOutSnDto> outSnDtosLW = rawOrderOutSnMapper.findInfoByPE(orderOutDtoLW);
            // 查询对应的PE管明细，根据长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
            List<RawOrderOutSnDto> outSnDtosPE = rawOrderOutSnMapper.findInfoByPE(orderOutDtoPE);

            BigDecimal amountPe = storageSn.getAmount() == null ? BigDecimal.ZERO : storageSn.getAmount();
            BigDecimal amountLwToPe = BigDecimal.ZERO;

            for (RawOrderOutSnDto outSnDtoPE : outSnDtosPE) {
                countPE += outSnDtoPE.getCount();
                if (outSnDtoPE.getAmount().compareTo(amountPe) == 0) {
                    ctPE = outSnDtoPE.getCount();
                }
            }

            for (RawOrderOutSnDto outSnDtoLw : outSnDtosLW) {
                countLW += outSnDtoLw.getCount();
                BigDecimal amountLw = outSnDtoLw.getAmount() == null ? BigDecimal.ZERO : outSnDtoLw.getAmount();
                if ((amountLw.subtract(amountPe).compareTo(Constant.X)) == 0) {
                    a = true;
                    ctLW = outSnDtoLw.getCount();
                    amountLwToPe = amountLw;
                    // 比较 当前已扫的 PE管数量 和 对应长度的钢管数量，PE管少就可以扫
                    if (ctPE < ctLW) {
                        a = true;
                    }
                    if (ctPE >= ctLW) {
                        resp.setCode(Constant.FAIL);
                        resp.setMsg("该长度的PE管数量已经满足对应钢管数量，不能多扫！");
                        return resp;
                    }
//                    if (!"2".equals(outSnDtoLw.getUserDefined1())){
//                        a = true;
//                        ctLW = outSnDtoLw.getCount();
//                        amountLwToPe = amountLw;
//                    }
                }
//                if ("2".equals(outSnDtoLw.getUserDefined1()) && a){
//                    resp.setCode(Constant.FAIL);
//                    resp.setMsg("该长度的PE管已经扫码完成！");
//                    return resp;
//                }
            }
            if (!a) {
                resp.setCode(Constant.FAIL);
                resp.setMsg("该PE管的长度不符合领料单已扫钢管的匹配规格！");
                return resp;
            }

            // 下面开始进行增改操作
            // 4.出库明细表，条码添加，状态：正常
            RawRequisitionSn requisitionSn = new RawRequisitionSn();
            requisitionSn.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());//领料单号
            requisitionSn.setRequisitionId(orderOutDtoPE.getRequisitionId()); // 主表主键
            requisitionSn.setContractNo(storageSn.getContractNo());//合同单号
            requisitionSn.setPurchaseNo(storageSn.getPurchaseNo());//采购订单号
            requisitionSn.setBarcode(storageSn.getBarcode());//条码
            requisitionSn.setModel(storageSn.getModel());//型号
            requisitionSn.setModelDesc(storageSn.getModelDesc());//型号描述
            requisitionSn.setModelType(storageSn.getModelType());//型号类型
            requisitionSn.setAmount(storageSn.getAmount());//数量
            requisitionSn.setUnit(storageSn.getUnit());//单位
            requisitionSn.setWhCode(storageSn.getWhCode());//仓库
            requisitionSn.setWdCode(storageSn.getWdCode());//区域
            requisitionSn.setWaCode(storageSn.getWaCode());//库区
            requisitionSn.setWlCode(storageSn.getWlCode());//库位
            requisitionSn.setMesStatus("0");//传MES标识
            requisitionSn.setScanStatus("0");//扫描状态 是否退扫
            requisitionSn.setCreateBy(rawOrderOutSnDto.getLoginName());//创建人
            requisitionSn.setGmtCreate(new Date());//创建时间
            requisitionSn.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            requisitionSn.setGmtModified(new Date());//修改时间
            requisitionSn.setActiveFlag("1");//是否有效
            upt += rawOrderOutSnMapper.createCode(requisitionSn);

/*            // 修改 出库明细表中 对应长度的 钢管明细的 配套状态
            RawOrderOutSnDto orderOutSnDtoLW = new RawOrderOutSnDto(); // 钢管
            orderOutSnDtoLW.setContractNo(orderOutDtoLW.getContractNo());
            orderOutSnDtoLW.setRequisitionNo(orderOutDtoLW.getRequisitionNo());
            orderOutSnDtoLW.setModel(orderOutDtoLW.getModel());
            orderOutSnDtoLW.setAmount(amountLwToPe);
            orderOutSnDtoLW.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            orderOutSnDtoLW.setGmtModified(new Date());//修改时间

            // 当 钢管已经扫完 且 PE管数量与钢管数只少1 的时候，PE管扫完当前条码后设置为扫码完成
            if ((ctLW - ctPE)==1 && "3".equals(orderOutDtoLW.getRequisitionStatus())){
                orderOutSnDtoLW.setUserDefined1("2");
            }else {
                orderOutSnDtoLW.setUserDefined1("1");
            }
//            if ((ctLW - ctPE)>1){
//                orderOutSnDtoLW.setUserDefined1("1");
//            }else if ((ctLW - ctPE)==1 && "3".equals(orderOutDtoLW.getRequisitionStatus())){
//                orderOutSnDtoLW.setUserDefined1("2");
//            }
            upt += rawOrderOutSnMapper.updateUdf1(orderOutSnDtoLW);*/

            // 5.修改出库主表
//            rawOrderOutSnDto.setModel(storageSn.getModel());//型号
//            rawOrderOutSnDto.setAmount(storageSn.getAmount());//数量
//            rawOrderOutSnDto.setContractNo(storageSn.getContractNo());//合同编号

            // 根据 PE管扫码进度 修改 对应的钢管 配套状态 0：未开始 1：配套中 2：完成
//            if ((countLW - countPE)>1){
//                // 修改主表钢管的配套状态为配套中
//                orderOutDtoLW.setUserDefined1("1");
//                orderOutDtoPE.setRequisitionStatus("1");
//            }else if ((countLW - countPE) == 1){
//                // 修改主表钢管的配套状态为配套完成
//                orderOutDtoLW.setUserDefined1("2");
//                orderOutDtoPE.setRequisitionStatus("3");
//            }
//            orderOutDtoLW.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
//            orderOutDtoLW.setGmtModified(new Date());//修改时间

/*            if ((countLW - countPE)==1 && "3".equals(orderOutDtoLW.getRequisitionStatus())){
                orderOutDtoPE.setRequisitionStatus("3");
            }else {
                orderOutDtoPE.setRequisitionStatus("1");
            }*/
//            // 操作出库主表，修改对应钢管的配套状态
//            upt += rawOrderOutMapper.updateOfPE(orderOutDtoLW);

            orderOutDtoPE.setRealAmount(storageSn.getAmount()); // 本次扫码数量赋值
            orderOutDtoPE.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            orderOutDtoPE.setGmtModified(new Date());//修改时间
            orderOutDtoPE.setRequisitionStatus("1");// 状态设为发货中
            // 修改 出库主表 PE管的 实发数量、发货状态
            upt += rawOrderOutMapper.updateInfo(orderOutDtoPE); // orderOutDtoPE

            // 6.库存明细表，条码改flag，状态：已出库
            storageSn.setBarcodeStatus("2");//状态改为已出库
            upt += rawStorageSnMapper.updateFlagByCode(storageSn);

            //扫码成功
            resp.setCode(Constant.SUCCESS);
        }
        return resp;
    }

    /**
     * @param storageSn
     * @param rawOrderOutSnDto
     * @return
     * @wzhg 1866 非PE管扫描
     */
    @Override
    @Transactional
    public HandResp scanElse(RawOrderOutSnDto rawOrderOutSnDto, RawStorageSn storageSn) {
        HandResp resp = new HandResp();
        int upt = 0;
        // 3.根据条码归属的【领料单号、合同号和型号】查询主表信息,判断订单下该型号扫描数量是否已经达到需求数量
        RawOrderOutDto orderOutDto = new RawOrderOutDto();
        orderOutDto.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());
        orderOutDto.setContractNo(storageSn.getContractNo());
        orderOutDto.setModel(storageSn.getModel());

        // 该步骤只是为了卡住 事物，没有对数据库进行实际有影响的操作 修改领料单 active_flag 为 1 （原值就是 1）
        rawOrderOutMapper.updateOrderStatus(orderOutDto);
        List<RawOrderOutDto> orderOutDtos = rawOrderOutMapper.findOrderInfo(orderOutDto);
        if (orderOutDtos.size() == 0) {
            resp.setCode(Constant.FAIL);
            resp.setMsg("该领料单内不包含该条码型号！");
            return resp;
        } else {
            orderOutDto = orderOutDtos.get(0);
            //判断是不是  L 和 W 类型（钢管） 1889wzhg 删除PE管的 一米闸口
            Boolean typeFlag = Constant.MODEL_L.equals(storageSn.getModelType()) || Constant.MODEL_W.equals(storageSn.getModelType());
//            Boolean typeFlag = Constant.MODEL_L.equals(storageSn.getModelType()) || Constant.MODEL_W.equals(storageSn.getModelType()) || Constant.MODEL_PE.equals(storageSn.getModelType());
            // 判断该物料添加后，长度是不是超出一米
            BigDecimal realAmount = orderOutDto.getRealAmount() == null ? BigDecimal.ZERO : orderOutDto.getRealAmount();
            BigDecimal requireAmount = orderOutDto.getRequireAmount() == null ? BigDecimal.ZERO : orderOutDto.getRequireAmount();
            BigDecimal stgamount = storageSn.getAmount() == null ? BigDecimal.ZERO : storageSn.getAmount();

            BigDecimal val = (realAmount.add(stgamount)).subtract(requireAmount);
            int a = val.compareTo(new BigDecimal("0"));
            int b = val.compareTo(new BigDecimal("1"));

            orderOutDto.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
            orderOutDto.setGmtModified(new Date());
            if (realAmount.compareTo(requireAmount) == 0 || realAmount.compareTo(requireAmount) == 1) {
                resp.setCode(Constant.FAIL);
                resp.setMsg("此型号已扫描完成！");
                return resp;
            } else if (typeFlag && (b == 1)) {
                // 钢管
                resp.setCode(Constant.FAIL);
                resp.setMsg("该物料长度过长！");
                return resp;
            } else {
                rawOrderOutSnDto.setUserDefined1("1"); // 暂借 udf1 保存领料单的发货状态
            }

/*            else if (typeFlag && (a >= 0 && b <=0)) {
                //钢管 已经扫码完成
                rawOrderOutSnDto.setUserDefined1("3"); // 暂借 udf1 保存领料单的发货状态
            } else {
                if (a < 0) {
                    rawOrderOutSnDto.setUserDefined1("1");
                } else if (a >= 0) {
                    rawOrderOutSnDto.setUserDefined1("3");
                }
            }*/
            // 4.出库主表 根据【领料单号、合同号、型号】修改【数量以及领料单状态：发货中 或 扫码完成】
            rawOrderOutSnDto.setModel(storageSn.getModel());//型号
            rawOrderOutSnDto.setAmount(storageSn.getAmount());//数量
            rawOrderOutSnDto.setContractNo(storageSn.getContractNo());//合同编号
            rawOrderOutSnDto.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
            rawOrderOutSnDto.setGmtModified(new Date());
            upt += rawOrderOutMapper.updateAmount(rawOrderOutSnDto);

            // 5.出库明细表，条码添加，状态：正常
            RawRequisitionSn requisitionSn = new RawRequisitionSn();
            requisitionSn.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo().toUpperCase());//领料单号
            requisitionSn.setRequisitionId(orderOutDto.getRequisitionId()); // 主表主鍵
            requisitionSn.setContractNo(storageSn.getContractNo());//合同单号
            requisitionSn.setPurchaseNo(storageSn.getPurchaseNo());//采购订单号
            requisitionSn.setBarcode(storageSn.getBarcode());//条码
            requisitionSn.setModel(storageSn.getModel());//型号
            requisitionSn.setModelDesc(storageSn.getModelDesc());//型号描述
            requisitionSn.setModelType(storageSn.getModelType());//型号类型
            requisitionSn.setAmount(storageSn.getAmount());//数量
            requisitionSn.setUnit(storageSn.getUnit());//单位
            requisitionSn.setWhCode(storageSn.getWhCode());//仓库
            requisitionSn.setWdCode(storageSn.getWdCode());//区域
            requisitionSn.setWaCode(storageSn.getWaCode());//库区
            requisitionSn.setWlCode(storageSn.getWlCode());//库位
            requisitionSn.setMesStatus("0");//传MES标识
            requisitionSn.setScanStatus("0");//扫描状态 是否退扫
            requisitionSn.setCreateBy(rawOrderOutSnDto.getLoginName());//创建人
            requisitionSn.setGmtCreate(new Date());//创建时间
            requisitionSn.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            requisitionSn.setGmtModified(new Date());//修改时间
            requisitionSn.setActiveFlag("1");//是否有效
            upt += rawOrderOutSnMapper.createCode(requisitionSn);
            // 6.库存明细表，条码改flag，状态：已出库
            storageSn.setBarcodeStatus("2");//状态改为已出库
            storageSn.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
            storageSn.setGmtModified(new Date());
            upt += rawStorageSnMapper.updateFlagByCode(storageSn);

            //扫码成功
            resp.setCode(Constant.SUCCESS);

        }

        return resp;
    }

    /**
     * @param rawOrderOutSnDto
     * @return
     * @Title delBarCode
     * @Description 退扫
     * @author luoteng
     * @date 2018年7月3日:下午3:10:07
     */
    @Override
    @Transactional
    public HandResp delBarCode(RawOrderOutSnDto rawOrderOutSnDto) {


        // 要判断退扫的是否是PE管，如果是，是否为匹配钢管的订单，如果是，判断该长度的PE管与对应的钢管数量是否一致
        // 如果PE管少，钢管要改为 配套中 ，该步骤是为了判断是否需要修改 user_defined1（PE管与钢管配套标识）

        HandResp resp = new HandResp();
        Date now = new Date();

        List<RawRequisitionSn> requisitionSnList = rawOrderOutSnMapper.findByCode(rawOrderOutSnDto);
        if (requisitionSnList.size() > 1) {
            resp.setCode(Constant.FAIL);
            resp.setMsg("出库明细中条码重复，请联系运维人员核查！");
            return resp;
        } else if (requisitionSnList.size() < 1) {
            resp.setCode(Constant.FAIL);
            resp.setMsg("该条码尚未扫描！");
            return resp;
        }

        RawRequisitionSn rawRequisitionSn = requisitionSnList.get(0);
//        MES回传标识 0：未传给MES;1：已传MES
        if(rawRequisitionSn.getMesStatus() != null && rawRequisitionSn.getMesStatus().equals("1")){
        	 resp.setCode(Constant.FAIL);
             resp.setMsg("该条码已经上传生产线（MES），不能退扫！");
             return resp;
        }

        // 出库主表 发货数量减少
//    	requisition_status 0 新建 1 发货中 2发货完成 3扫码完成
        rawOrderOutSnDto.setUserDefined1("1"); // 暂借 udf1 保存领料单的发货状态
        rawOrderOutSnDto.setModel(rawRequisitionSn.getModel());//型号
//        默认管件 扫码的时候 写入1
        rawOrderOutSnDto.setAmount(rawRequisitionSn.getAmount());//数量
        rawOrderOutSnDto.setContractNo(rawRequisitionSn.getContractNo());//合同编号
        rawOrderOutSnDto.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
        rawOrderOutSnDto.setGmtModified(now);
        rawOrderOutMapper.updateAmountMinus(rawOrderOutSnDto);


        // 出库明细表，条码删除
        RawRequisitionSn upob = new RawRequisitionSn();
        upob.setRequisitionSnId(rawRequisitionSn.getRequisitionSnId());
        upob.setActiveFlag("0");//是否有效
        upob.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
        upob.setGmtModified(now);
        rawRequisitionSnMapper.updateBySelect(upob);

        // 库存明细表，条码改flag，状态：可用
        RawStorageSn rawStorageSn = new RawStorageSn();
        rawStorageSn.setBarcode(rawOrderOutSnDto.getBarcode());
//        0可用；1 冻结；2 已出库
        rawStorageSn.setBarcodeStatus("0");
        rawStorageSn.setLastModifiedBy(rawOrderOutSnDto.getLoginName());
        rawStorageSn.setGmtModified(now);
        rawStorageSnMapper.updateFlagByCode(rawStorageSn);

//        手持展示字段
        resp.setList(requisitionSnList);
        resp.setCode(Constant.SUCCESS);
        return resp;
    }

    /**
     * @param rawOrderOutDto
     * @return
     * @wzhg 1873 判断退扫操作是否完成
     */
    public HandResp delJudge(RawOrderOutDto rawOrderOutDto) {
        HandResp result = new HandResp();
        Boolean lean = false;

        // 1.根据领料单号 查询 领料单信息
        List<RawOrderOutDto> orderOutDtos = rawOrderOutMapper.findOrderInfo(rawOrderOutDto);

        RawOrderOutDto orderOutDtoLW = new RawOrderOutDto(); // 钢管
        RawOrderOutDto orderOutDtoPE = new RawOrderOutDto(); // PE管
        if (orderOutDtos.size() >= 2) {
            for (RawOrderOutDto orderOutDto : orderOutDtos) {
                if (Constant.MODEL_L.equals(orderOutDto.getModelType()) || Constant.MODEL_W.equals(orderOutDto.getModelType())) {
                    orderOutDtoLW = orderOutDto;
                } else if (Constant.MODEL_PE.equals(orderOutDto.getModelType())) {
                    orderOutDtoPE = orderOutDto;
                }
            }
        } else {
            result.setCode(Constant.FAIL);
            result.setMsg("领料单信息异常！");
            return result;
        }
        // 2.根据领料单号 查询 领料出库明细信息，根据 原材料规格（长度）进行分组查询
        // 查询对应的钢管明细，根据长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
        List<RawOrderOutSnDto> outSnDtosLW = rawOrderOutSnMapper.findInfoByPE(orderOutDtoLW);
        // 查询对应的PE管明细，根据长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
        List<RawOrderOutSnDto> outSnDtosPE = rawOrderOutSnMapper.findInfoByPE(orderOutDtoPE);

        for (RawOrderOutSnDto pe : outSnDtosPE) {
            lean = false;
            for (RawOrderOutSnDto lw : outSnDtosLW) {
                if ((pe.getAmount().add(Constant.X)).compareTo(lw.getAmount()) == 0) {
                    if (pe.getCount() > lw.getCount()) {
                        lean = true;
                        result.setCode(Constant.FAIL);
                        result.setMsg("领料单中长度为" + pe.getAmount().toString() + "的" + pe.getModel() + "型号PE管待退扫！");
                        return result;
                    } else {
                        lean = true;
                    }
                    break;
                }
            }

            // 该长度的PE管找不到对应的钢管（之前匹配的钢管都退扫了，PE管还没退完）
            if (!lean) {
                result.setCode(Constant.FAIL);
                result.setMsg("领料单中长度为" + pe.getAmount().toString() + "的" + pe.getModel() + "型号PE管待退扫！");
                return result;
            }
        }

        result.setCode(Constant.SUCCESS);
        return result;
    }

    /**
     * @param storageSn
     * @param rawOrderOutSnDto
     * @return
     * @wzhg 1866 PE管扫描 浮动匹配
     */
    @Override
    @Transactional
    public HandResp scanPE1(RawOrderOutSnDto rawOrderOutSnDto, RawStorageSn storageSn) {
        HandResp resp = new HandResp();
        Boolean a = false;  // 判断PE管长度与已扫的各个钢管的长度是否匹配
        int upt = 0;
        Long countLW = 0l; // 正在扫描的PE管对应的钢管型号的已扫总数（所有长度）
        Long countPE = 0l; // 正在扫描的PE管归属型号的已扫总数（所有长度的都包含）
        Long ctLW = 0l; //    正在扫描的PE管对应长度的钢管的已扫数量
        Long ctPE = 0l; //    正在扫描的PE管对应的型号，长度的已扫数量，最终 ctPE 与 ctLW相等，该长度的PE管就算扫完了
        int flag = 0;
        // 3.判断型号数量是否等于需求，达到需求值，不允许再扫，如果没达到，继续
        // 3.根据条码归属的【领料单号、合同号和型号】查询主表信息,判断订单下该型号扫描数量是否已经达到需求数量
        RawOrderOutDto orderOutDtoPE = new RawOrderOutDto(); // PE管
        RawOrderOutDto orderOutDtoLW = new RawOrderOutDto(); // 钢管
        orderOutDtoPE.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());
        orderOutDtoPE.setContractNo(storageSn.getContractNo());
        orderOutDtoPE.setModel(storageSn.getModel());

        // 该步骤只是为了卡住 事物，没有对数据库进行实际有影响的操作 修改领料单 active_flag 为 1 （原值就是 1）
        rawOrderOutMapper.updateOrderStatus(orderOutDtoPE);
        List<RawOrderOutDto> orderOutDtosPE = rawOrderOutMapper.findOrderInfo(orderOutDtoPE);
        if (orderOutDtosPE.size() == 0) {
            resp.setCode(Constant.FAIL);
            resp.setMsg("该领料单内不包含该条码型号！");
            return resp;
        } else {
            orderOutDtoPE = orderOutDtosPE.get(0);
            // 用id区别PE管和钢管 后续操作以requisitionId作为身份牌
            // 根据PE管的领料单查到对应的钢管领料信息,判断钢管是否全部扫完，钢管没扫完，不允许扫PE管
            orderOutDtoLW.setContractNo(storageSn.getContractNo());
            orderOutDtoLW.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo());
            List<RawOrderOutDto> orderOutDtosLW = rawOrderOutMapper.findOrderInfo(orderOutDtoLW);

            for (RawOrderOutDto order : orderOutDtosLW) {
                if (Constant.MODEL_W.equals(order.getModelType()) || Constant.MODEL_L.equals(order.getModelType())) {
                    orderOutDtoLW = order; // PE管对应的钢管领料信息
                    flag = 1;
                }
            }
            if (flag == 0) {
                resp.setCode(Constant.FAIL);
                resp.setMsg("找不到与该PE管对应的钢管领料信息，请核查！");
                return resp;
            }
            // 查询对应的钢管明细，根据长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
            List<RawOrderOutSnDto> outSnDtosLW = rawOrderOutSnMapper.findInfoByPE(orderOutDtoLW);
            // 查询对应的PE管明细，根据PE管匹配的钢管长度分类统计个数，PE数要配套相应长度以及个数(参数：领料单号、合同号、型号)
            List<RawOrderOutSnDto> outSnDtosPE = rawOrderOutSnMapper.findInfoByPE1(orderOutDtoPE);

            BigDecimal amountPe = storageSn.getAmount() == null ? BigDecimal.ZERO : storageSn.getAmount();
            BigDecimal amountLwToPe = BigDecimal.ZERO;

            for (RawOrderOutSnDto outSnDtoLw : outSnDtosLW) {

                countLW += outSnDtoLw.getCount();
                if (!a) {
                    BigDecimal amountLw = outSnDtoLw.getAmount() == null ? BigDecimal.ZERO : outSnDtoLw.getAmount();
                    double diff = amountLw.subtract(amountPe).doubleValue();

                    if (diff >= Constant.min && diff <= Constant.max) {
                        a = true;
                        ctLW = outSnDtoLw.getCount();
                        amountLwToPe = amountLw;

                        for (RawOrderOutSnDto outSnDtoPE : outSnDtosPE) {
                            countPE += outSnDtoPE.getCount();
                            if (outSnDtoPE.getLength().compareTo(amountLwToPe) == 0) {
                                ctPE = outSnDtoPE.getCount();
                            }
                        }

                        // 比较 当前已扫的 PE管数量 和 对应长度的钢管数量，PE管少就可以扫
                        if (ctPE < ctLW) {
                            a = true;
                        }
                        if (ctPE >= ctLW) {
                            resp.setCode(Constant.FAIL);
                            resp.setMsg("该长度的PE管数量已经满足对应钢管数量，不能多扫！");
                            return resp;
                        }
                    }
                }

            }
            if (!a) {
                resp.setCode(Constant.FAIL);
                resp.setMsg("该PE管的长度不符合领料单已扫钢管的匹配规格！");
                return resp;
            }

            // 下面开始进行增改操作
            // 4.出库明细表，条码添加，状态：正常
            RawRequisitionSn requisitionSn = new RawRequisitionSn();
            requisitionSn.setRequisitionNo(rawOrderOutSnDto.getRequisitionNo().toUpperCase());//领料单号
            requisitionSn.setRequisitionId(orderOutDtoPE.getRequisitionId()); // 主表主键
            requisitionSn.setContractNo(storageSn.getContractNo());//合同单号
            requisitionSn.setPurchaseNo(storageSn.getPurchaseNo());//采购订单号
            requisitionSn.setBarcode(storageSn.getBarcode());//条码
            requisitionSn.setModel(storageSn.getModel());//型号
            requisitionSn.setModelDesc(storageSn.getModelDesc());//型号描述
            requisitionSn.setModelType(storageSn.getModelType());//型号类型
            requisitionSn.setAmount(storageSn.getAmount());//数量
            requisitionSn.setLength(amountLwToPe); //记录PE管匹配的钢管的长度
            requisitionSn.setUnit(storageSn.getUnit());//单位
            requisitionSn.setWhCode(storageSn.getWhCode());//仓库
            requisitionSn.setWdCode(storageSn.getWdCode());//区域
            requisitionSn.setWaCode(storageSn.getWaCode());//库区
            requisitionSn.setWlCode(storageSn.getWlCode());//库位
            requisitionSn.setMesStatus("0");//传MES标识
            requisitionSn.setScanStatus("0");//扫描状态 是否退扫
            requisitionSn.setCreateBy(rawOrderOutSnDto.getLoginName());//创建人
            requisitionSn.setGmtCreate(new Date());//创建时间
            requisitionSn.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            requisitionSn.setGmtModified(new Date());//修改时间
            requisitionSn.setActiveFlag("1");//是否有效
            upt += rawOrderOutSnMapper.createCode(requisitionSn);

            orderOutDtoPE.setRealAmount(storageSn.getAmount()); // 本次扫码数量赋值
            orderOutDtoPE.setLastModifiedBy(rawOrderOutSnDto.getLoginName());//修改人
            orderOutDtoPE.setGmtModified(new Date());//修改时间
            orderOutDtoPE.setRequisitionStatus("1");// 状态设为发货中
            // 修改 出库主表 PE管的 实发数量、发货状态
            upt += rawOrderOutMapper.updateInfo(orderOutDtoPE); // orderOutDtoPE

            // 6.库存明细表，条码改flag，状态：已出库
            storageSn.setBarcodeStatus("2");//状态改为已出库
            upt += rawStorageSnMapper.updateFlagByCode(storageSn);

            //扫码成功
            resp.setCode(Constant.SUCCESS);
        }
        return resp;
    }
}
